// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#pragma once

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/bithumb/api_order/native_private_client.h"
#include "coin2/exchange/bithumb/api_util/order_manager.h"
#include "coin2/exchange/bithumb/symbology/product.h"

namespace coin2::exchange::bithumb::api_order {

class BithumbRestAsyncAsioSubscriber : public base::order::RestSubscriber {
 public:
  using BithumbProduct = coin2::exchange::bithumb::symbology::BithumbProduct;
  using RestParams = coin2::exchange::order::BithumbRestParams;
  using RestClient = BithumbNativePrivateClient;

 public:
  BithumbRestAsyncAsioSubscriber(
      coin2::exchange::base::order::NativePrivateClient* rest_client,
      coin2::exchange::base::api_base::NativeHttpAsioDriver* http_driver,
      const coin2::exchange::order::PrivateSubscriberConfig& config)
      : base::order::RestSubscriber(rest_client, http_driver, config) {
    order_mgr_ = std::make_unique<api_util::OrderManager>();
  }

  auto rest_client() -> RestClient* { return dynamic_cast<RestClient*>(rest_client_); }
  void QueryBalance();
  void QueryOpenOrders(const std::pair<std::string, std::string>& ccy);
  void QueryFills(const std::pair<std::string, std::string>& ccy);
  void QueryFillsV2();
  void SubscribeAsync() override;
  auto GetCurrencies() -> const std::vector<std::pair<std::string, std::string>>& {
    static std::vector<std::pair<std::string, std::string>> currencies = [this]() -> auto{
      std::vector<std::pair<std::string, std::string>> vec;
      auto timestamp = GetCurrentTimestamp();
      for (const auto& native_symbol : this->native_symbols()) {
        // assumed there is no duplicated native symbol
        auto product = BithumbProduct::FromStr(native_symbol, timestamp);
        auto currency_pair =
            std::make_pair(product.base().native_currency(), product.quote().native_currency());
        vec.push_back(std::move(currency_pair));
      };
      return vec;
    }
    ();
    return currencies;
  }
  auto GetMutableOrderManager() -> api_util::OrderManager* { return order_mgr_.get(); }

 private:
  std::unique_ptr<api_util::OrderManager> order_mgr_ = {};
};

}  // namespace coin2::exchange::bithumb::api_order
